

package jetbrains.buildServer.server.rest.jersey;

import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.spi.inject.Injectable;
import com.sun.jersey.spi.inject.InjectableProvider;
import java.lang.reflect.Type;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.ext.Provider;
import jetbrains.buildServer.ServiceLocator;
import jetbrains.buildServer.server.rest.ApiUrlBuilder;
import jetbrains.buildServer.server.rest.RequestPathTransformInfo;
import jetbrains.buildServer.server.rest.util.BeanContext;
import jetbrains.buildServer.server.rest.util.BeanFactory;
import org.springframework.stereotype.Component;

/**
 * @author Yegor.Yarko
 *         Date: 15.11.2009
 */
@Provider
@Component
public class BeanContextProvider implements InjectableProvider<Context, Type>, Injectable<BeanContext> {
  private final RequestPathTransformInfo myRequestPathTransformInfo;

  //TODO: using request-specific field in singleton provider
  //TODO: may lead to concurrency issue as this instance is
  //TODO: created by spring not by Jersey!
  @Context private HttpHeaders headers;
  @Context private HttpServletRequest request;

  private final BeanFactory myFactory;
  private final ServiceLocator myServiceLocator;

  public BeanContextProvider(final RequestPathTransformInfo requestPathTransformInfo, final BeanFactory factory, final ServiceLocator serviceLocator) {
    myRequestPathTransformInfo = requestPathTransformInfo;
    myFactory = factory;
    myServiceLocator = serviceLocator;
  }

  /**
   * This bean has PerRequest scope because of "headers" and "request"
   * fields above, which should be re-injected every time per request.
   */
  @Override
  public ComponentScope getScope() {
    return ComponentScope.PerRequest;
  }

  @Override
  public Injectable getInjectable(final ComponentContext ic, final Context context, final Type type) {
    if (type.equals(BeanContext.class)) {
      return this;
    }
    return null;
  }

  @Override
  public BeanContext getValue() {
    return new BeanContext(myFactory, myServiceLocator, new ApiUrlBuilder(new SimplePathTransformer(request, headers, myRequestPathTransformInfo)));
  }
}